#include "depui/depui.h"

#ifdef MX_PLATFORM_DEGFX

#   define MXMODULE_LOADFONT
#   define MXMODULE_FONTDRAW
#   include "degfx/degfx.h"
#   include <string.h>

static const MX_PLATFORM_FONT mx__degfx_font[] = {
#   if defined(MXMODULE_FONT_8X8)
	{&mx_font_8x8, "fixed 8x8"},
#   endif
#   if defined(MXMODULE_FONT_8X14)
	{&mx_font_8x14, "fixed 8x14"},
#   endif
#   if defined(MXMODULE_FONT_8X16)
	{&mx_font_8x16, "fixed 8x16"},
#   endif
	{0, 0}
};

#   define MX__ARRAY(a) (sizeof(a)/sizeof(a[0]))

const MX_PLATFORM_FONT *mx_platform_font_system(const int i)
{
	if (i < 0)
		return &mx__degfx_font[0];

	if (i < (int) MX__ARRAY(mx__degfx_font) - 1)
		return &mx__degfx_font[i];

	return 0;
}

void *mx_platform_font_load(const char *filename)
{
	assert(filename);

	return mx_font_pcx(filename, 0x20);
}

const char *mx_platform_font_path(void)
{
	return "./*.pcx";
}

void mx_platform_font_free(void *font)
{
	MX_FONT *f;

	assert(font);

	f = (MX_FONT *) font;

	mx_delete(f);
}

unsigned int mx_platform_font_height(void *font)
{
	MX_FONT *f;

	f = (MX_FONT *) font;

	return mx_font_height(f);
}

unsigned int mx_platform_font_width(void *font, const char *text, int len)
{
	MX_FONT *f;

	assert(text);

	f = (MX_FONT *) font;

	return mx_font_width(f, text, len);
}

void mx__degfx_textchunks(const MX_TEXTUAL_DATA * textual, MX_PIXEL fore, int x, int y)
{
	int offx = 0;
	int offy = 0;
	const int x1 = mx_x1(textual);
	const int y1 = mx_y1(textual);
	MX__TEXTCHUNK *chunk;

	/* Left and top alignment is correct with offset 0 */
	if (textual->_align & MX_ALIGN_RIGHT)
		offx = mx_w(textual) - textual->_textwidth - 2 * x;
	if (textual->_align & MX_ALIGN_HCENTER)
		offx = (mx_w(textual) - textual->_textwidth - 2 * x) / 2;

	if (textual->_align & MX_ALIGN_BOTTOM)
		offy = mx_h(textual) - textual->_textheight - 2 * y;
	if (textual->_align & MX_ALIGN_VCENTER)
		offy = (mx_h(textual) - textual->_textheight - 2 * y) / 2;

	chunk = mx_dllist_first(textual);
	while (chunk) {
		int len = 0;
		const char *text = mx_string_text(&chunk->text, &len);

		if (chunk->cursor) {
			if (mx_focused(textual)) {
				mx_box(x + x1 + chunk->rect.x1, y + y1 + chunk->rect.y1, x + x1 + chunk->rect.x2, y + y1 + chunk->rect.y2, 1,
					   MXTRANS(MXCOLOR_grey70, 128), MXTRANS(MXCOLOR_grey20, 128));
				mx_rectfill(x + x1 + chunk->rect.x1 + 1, y + y1 + chunk->rect.y1 + 1, x + x1 + chunk->rect.x2 - 1, y + y1 + chunk->rect.y2 - 1,
							MXTRANS(MXCOLOR_grey50, 128));
			} else {
				mx_box(x + x1 + chunk->rect.x1, y + y1 + chunk->rect.y1, x + x1 + chunk->rect.x2, y + y1 + chunk->rect.y2, 1,
					   MXTRANS(MXCOLOR_grey50, 128), MXTRANS(MXCOLOR_grey50, 128));
			}
		}

		if (text) {
			MX_FONT *chunkfont = (MX_FONT *) mx__textual_platform_font(textual);

			mx_font_draw(chunkfont, text, len, x + x1 + chunk->rect.x1 + offx, y + y1 + chunk->rect.y1 + offy, fore);
		}
		chunk = mx_dllist_next(chunk);
	}
}

static const MX_PLATFORM_RESOLUTION mx__degfx_resolutions[] = {
#   ifdef __QDOS__
	{256, 256, "256 x 256"},
	{512, 256, "512 x 256"},
	{1024, 512, "1024 x 512"},
	{1024, 768, "1024 x 768"},
#   else
	{320, 200, "320 x 200"},
	{640, 480, "640 x 480"},
	{800, 600, "800 x 600"},
	{1024, 768, "1024 x 768"},
	{1280, 1024, "1280 x 1024"},
#   endif
	{0, 0, 0}
};

static const MX_PLATFORM_DEPTH mx__degfx_depths[] = {
	{2, "2"},
	{4, "4"},
	{8, "8"},
	{16, "16"},
	{24, "24"},
	{32, "32"},
	{0, 0}
};

static const MX_PLATFORM_DRIVER mx__degfx_drivers[] = {
#   if defined(MXMODULE_DRIVER_FULLSCREEN)
	{&mx_driver_fullscreen, "fullscreen"},
#   endif
#   if defined(MXMODULE_DRIVER_WINDOWED)
	{&mx_driver_windowed, "windowed"},
#   endif
#   if defined(MXMODULE_DRIVER_VGA)
	{&mx_driver_vga, "vga"},
#   endif
#   if defined(MXMODULE_DRIVER_13H)
	{&mx_driver_13h, "13h"},
#   endif
	{0, 0}
};

static const MX_PLATFORM_THEME mx__degfx_themes[] = {
#   if defined(MXMODULE_THEME_DEFAULT)
	{&mx_theme_default, "Default"},
#   endif
#   if defined(MXMODULE_THEME_WIN95)
	{&mx_theme_win95, "Win95"},
#   endif
#   if defined(MXMODULE_THEME_ROUNDED)
	{&mx_theme_rounded, "Rounded"},
#   endif
	{0, 0}
};

void mx_platform_modes(const MX_PLATFORM_DRIVER * d[], const MX_PLATFORM_RESOLUTION * r[], const MX_PLATFORM_DEPTH * c[],
					   const MX_PLATFORM_THEME * t[])
{
	*d = mx__degfx_drivers;
	*r = mx__degfx_resolutions;
	*c = mx__degfx_depths;
	*t = mx__degfx_themes;
}

unsigned mx_platform_start(int w, int h, int c, const void *driver)
{
	MX_GFX_ARGS args;

	memset(&args, 0, sizeof(args));
	args.w = w;
	args.h = h;
	args.c = c;
	args.driver = (const MX_DRIVER *) driver;
	args.redraw = mx__gui_redraw;

	return mx_gfx_start(&args);
}

void mx_platform_stop(void)
{
	mx_gfx_stop();
}

unsigned mx_platform_clip(const MX_RECT * r)
{
	return mx_bitmap_clip(MXSCREEN, r);
}

const MX_RECT *mx_platform_rect(void)
{
	return (&(mx_gfx_info()->screen));
}

unsigned mx_platform_poll(void)
{
	return mx_gfx_poll();
}

void mx_platform_dirty(const MX_RECT * rect)
{
	mx_gfx_dirty(rect);
}

unsigned mx_platform_pointer(int *px, int *py, int *pb)
{
	return mx_gfx_pointer(px, py, pb);
}

unsigned mx_platform_key(int *scan, int *ascii)
{
	return mx_gfx_key(scan, ascii);
}

#endif
